package goutils

import (
	"fmt"
	"go/ast"
	"go/parser"
	"go/token"
	"go/types"
	"reflect"
	"strings"
)

func GetFieldName(field interface{}) string {
	types := reflect.TypeOf(field)
	return types.Name()

}

// toSnakeCase函数接受一个字符串类型的参数s，将其转换为蛇形命名方式，并返回转换后的字符串
func ToSnakeCase(s string) string {

	data := make([]byte, 0, len(s)*2)
	j := false
	num := len(s)
	for i := 0; i < num; i++ {
		d := s[i]
		// or通过ASCII码进行大小写的转化
		// 65-90（A-Z），97-122（a-z）
		//判断如果字母为大写的A-Z就在前面拼接一个_
		if i > 0 && d >= 'A' && d <= 'Z' && j {
			data = append(data, '_')
		}
		if d != '_' {
			j = true
		}
		data = append(data, d)
	}
	//ToLower把大写字母统一转小写
	return strings.ToLower(string(data[:]))

	//re := regexp.MustCompile("([A-Z]+|[0-9]+)")
	//words := re.FindAllString(s, -1)
	//for i, word := range words {
	//	words[i] = strings.ToLower(word)
	//}
	//return strings.Join(words, "_")
}

// toCamelCase函数接受一个字符串类型的参数s，将其转换为大写的驼峰式命名方式，并返回转换后的字符串
func ToCamelCase(s string) string {
	words := strings.Split(s, "_")
	for i, word := range words {
		words[i] = strings.ToUpper(word)
	}
	return strings.Join(words, "")
}

func ScanStructs(packageName string) []string {
	structs := make([]string, 0)

	// 创建一个文件集合
	fset := token.NewFileSet()
	packageName = "go_entity.go"
	// 解析指定包名的所有Go源文件
	pkgs, err := parser.ParseDir(fset, packageName, nil, parser.AllErrors)
	if err != nil {
		fmt.Println("Error parsing package:", err)
		return structs
	}

	// 遍历解析的包
	for _, pkg := range pkgs {
		// 检查包名是否匹配
		if pkg.Name != packageName {
			continue
		}

		// 类型检查器
		conf := types.Config{}
		// 获取包的类型信息
		info := types.Info{
			Types: make(map[ast.Expr]types.TypeAndValue),
		}
		// 遍历包的每个文件
		for _, file := range pkg.Files {
			// 类型检查
			_, err := conf.Check(packageName, fset, []*ast.File{file}, &info)
			if err != nil {
				fmt.Println("Error checking package:", err)
				return structs
			}
		}

		// 遍历包中的每个对象
		for ident, obj := range info.Defs {
			// 判断对象是否为结构体类型
			if typ, ok := obj.(*types.TypeName); ok {
				if _, ok := typ.Type().Underlying().(*types.Struct); ok {
					fmt.Println("判断对象是否为结构体类型 checking package:", structs, ident.Name)
					structs = append(structs, ident.Name)
				}
			}
		}
	}

	return structs
}

type Person struct {
	Name   string
	Age    int
	Height float64
}

func (receiver Person) name1() {
	fmt.Println("----name1-")
}
func (receiver Person) name2() {
	fmt.Println("---name2--")
}
func (receiver Person) name3() {
	fmt.Println("--name3---")
}

func MainStruct() {
	t := reflect.TypeOf(Person{})
	var j = t.NumMethod()
	for ii := 0; ii < j; ii++ {
		method := t.Method(ii)
		fmt.Printf("NumMethod %d: %s\n", ii+1, method.Name)
		fmt.Printf("NumMethod Type: %s\n", method.Type)
		fmt.Printf("NumMethod Func: %s\n", method.Func)
		fmt.Printf("NumMethod PkgPath: %v\n", method.PkgPath)
		fmt.Println("-----")
	}

	// 遍历结构体的字段
	for i := 0; i < t.NumField(); i++ {
		field := t.Field(i)
		fmt.Printf("Field %d: %s\n", i+1, field.Name)
		fmt.Printf("Type: %s\n", field.Type)
		fmt.Printf("Tag: %s\n", field.Tag)
		fmt.Printf("Anonymous: %v\n", field.Anonymous)
		fmt.Println("-----")
	}
}

// 定义一个接口
type ControllerInterface interface {
	Method()
}

// 定义两个实现类
type MyStruct1 struct{}
type MyStruct2 struct{}

// 实现接口的方法
func (s MyStruct1) Method() {}
func (s MyStruct2) Method() {}
